package evaluation;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;

import utils.Compteur;
import utils.Constante;

import modele.AbsPiece;
import modele.Pousser;
import modele.Pousseur;
import mouvement.GenerateurMouvement;

public class Noeud {

    private int[][] grille;
    private GenerateurMouvement gM;
    private boolean max;
    private String mouvement;
    private ArrayList<Noeud> listNoeud;
    private int profondeur;
    
    public Noeud(int[][] grille, String mouvement, boolean type, int profondeur){
        this.profondeur = profondeur;
        this.grille = new int[8][8]; 
        max = type;
        
        for(int i = 0; i < grille.length; i ++) {
            for(int j = 0; j < grille[i].length; j ++) {
                this.grille[i][j] = grille[i][j];
            }
        }
        this.mouvement = mouvement;
        String mcase1 = mouvement.substring(0,2);
        String mcase2 = mouvement.substring(2,4);
        
        int mcases1Col = mcase1.charAt(0) - 'A';
        int mcases1Lig = 8 - Integer.parseInt(String.valueOf(mcase1.charAt(1)));
        int mcases2Col = mcase2.charAt(0) - 'A';
        int mcases2Lig = 8 - Integer.parseInt(String.valueOf(mcase2.charAt(1)));

        this.grille[mcases2Col][mcases2Lig] = this.grille[mcases1Col][mcases1Lig];
        this.grille[mcases1Col][mcases1Lig] = 0;
        
        gM = new GenerateurMouvement();
        
        for(int i = 0; i < grille.length; i ++) {
            for(int j = 0; j < grille[i].length; j ++) {
                if(Evaluateur.isWhitePlayer() != max) {
                    if(this.grille[i][j] == 4) {
                        AbsPiece piece = new Pousseur(String.valueOf(Evaluateur.colonne[i]) + String.valueOf(8 - j), this.grille[i][j]);
                        gM.addPiece(String.valueOf(Evaluateur.colonne[i]) + String.valueOf(8 - j), piece);
                    } else if(this.grille[i][j] == 3){
                        AbsPiece piece = new Pousser(String.valueOf(Evaluateur.colonne[i]) + String.valueOf(8 - j) , this.grille[i][j]);
                        gM.addPiece(String.valueOf(Evaluateur.colonne[i]) + String.valueOf(8 - j), piece);
                    }
                } else {
                    if(this.grille[i][j] == 2) {
                        AbsPiece piece = new Pousseur(String.valueOf(Evaluateur.colonne[i]) + String.valueOf(8 - j), this.grille[i][j]);
                        gM.addPiece(String.valueOf(Evaluateur.colonne[i]) + String.valueOf(8 - j), piece);
                    } else if(this.grille[i][j] == 1){
                        AbsPiece piece = new Pousser(String.valueOf(Evaluateur.colonne[i]) + String.valueOf(8 - j) , this.grille[i][j]);
                        gM.addPiece(String.valueOf(Evaluateur.colonne[i]) + String.valueOf(8 - j), piece);
                    }
                }
            }
        }
        
        listNoeud = new ArrayList<Noeud>();
        if(this.profondeur < Constante.PROFONDEUR) {
            LinkedList<String> mouvements = gM.getPossibilites(this.grille);

            Iterator<String> itMouvement = mouvements.iterator();
            while(itMouvement.hasNext()) {
                String currMouvement = itMouvement.next();
                Noeud plateau = new Noeud(this.grille, currMouvement, !max, this.profondeur + 1);    
                listNoeud.add(plateau);
            }
        }
    }

    public boolean isMax() {
        return max;
    }

    public int CalculerMinMaxAB(int profondeur, int a, int b) {
        Iterator<Noeud> itNoeud = listNoeud.iterator();
        int retour = 0;
        
        if(listNoeud.size() == 0) {
            retour = Evaluateur.evaluateBoard(this.grille);
        } else {
            if(!isMax()){
                if(Evaluateur.evaluateBoard(this.grille) == 1000) {
                    return 1001;
                }
                retour = a;
                while(itNoeud.hasNext() && Compteur.getTime() < Constante.MAX_TEMPS) {
                    Noeud nCourant = itNoeud.next();
                    int alpha = -1000000;
                    int score = nCourant.CalculerMinMaxAB(profondeur - 1,Math.max(a,alpha),b);
                    alpha = Math.max(alpha,score);
                    retour = alpha;
                    if(alpha >= b)
                        return alpha;
                }
                return retour;
            } else {
                if(Evaluateur.evaluateBoard(this.grille) == -1000) {
                    return -1001;
                }
                
                retour = b;
                while(itNoeud.hasNext() && Compteur.getTime() < Constante.MAX_TEMPS) {
                    Noeud nCourant = itNoeud.next();
                    int beta = 1000000;
                    int score = nCourant.CalculerMinMaxAB(profondeur - 1,a,Math.min(beta,b));
                    beta = Math.min(score,beta);
                    retour = beta;
                    if(beta <= a)
                        return beta;
                }
                return retour;
            }
        }
        return retour;
    }

    public String getMouvement() {
        return mouvement;
    }
}
